#pragma once
#include <iostream>
#include "Thread.hpp"
#include <vector>
#include <queue>
#include <pthread.h>
#include"Log.hpp"
#include"Task.hpp"
using namespace ThreadModule;
using namespace std;
const static int defaultthreadnum = 3;
template <typename T>
class ThreadPool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    void ThreadWakeupAll()
    {
        pthread_cond_broadcast(&_cond);
    }
public:
    ThreadPool(int threadnum = defaultthreadnum) : _threadnum(threadnum), _waitnum(0), _isrunning(false)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
         LOG(INFO," ThreadPool Construct()");
    }
    void Print(string name)
    {
        while (1)
        {
            cout << "haha" << name << endl;
            sleep(1);
        }
    }
    void HandlerTask(string name)
    {
        LOG(INFO,"%s is running...",name.c_str());
        while (1)
        {
            LockQueue();
            // 如果队列里面没有数据
            while (_task_queue.empty()&&_isrunning )
            {
                _waitnum++;
                ThreadSleep();
                _waitnum--;
            }
            //线程池退出&&任务队列为空
            if(_task_queue.empty()&&!_isrunning)
            {
                UnlockQueue();
                break;
            }
            //如果线程池没有退出&&任务队列不为空

            //线程池已经退出&&任务队列不为空

            // 处理任务
            T t = _task_queue.front();
            _task_queue.pop();
            UnlockQueue();
            LOG(DEBUG,"%s get a task ",name.c_str());
            // 处理任务，这个人物属于线程独占的任务
            t();
            LOG(DEBUG,"%s handler a task ,result is:%s",name.c_str(),t.ResultToString().c_str());
        }
    }
    void InitThreadPool()
    {
        // 构建所有线程，并不启动
        for (int num = 0; num < _threadnum; num++)
        {
            string name = "thread-" + to_string(num + 1);
            //_threads.emplace_back(Print,name);
            _threads.emplace_back(bind(&ThreadPool::HandlerTask, this, std::placeholders::_1), name);
        LOG(INFO,"InitThread %s done",name.c_str());
        }
         _isrunning = true;
        
    }
    void Start()
    {
        for (auto &thread : _threads)
        {
            thread.Start();
        }
       
    }
    void Stop()
    {
        LockQueue();
        _isrunning=false;
        ThreadWakeupAll();
        UnlockQueue();

    }
    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join();
            LOG(INFO,"%s is quit",thread.name().c_str());
        }
    }
    bool Enqueue(const T &t)
    {
        bool ret=false;
        LockQueue();
        if (_isrunning)
        {
            _task_queue.push(t);
            if (_waitnum > 0)
            {
                ThreadWakeup();
            }
            LOG(INFO,"enqueue task success");
            ret=true;
        }
        UnlockQueue();
        return ret;
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _threadnum;
    vector<Thread> _threads;
    queue<T> _task_queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    int _waitnum;
    bool _isrunning;
};